Categories
Material UI

Material UI — Popovers

Spread the love

Material UI is a Material Design library made for React.

It’s a set of React components that have Material Design styles.

In this article, we’ll look at how to add popovers with Material UI.

Simple Popover

Popovers let us display some content over other things.

To add it, we can use the Popover component.

For example, we can write:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Popover from "@material-ui/core/Popover";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";

const useStyles = makeStyles(theme => ({
  typography: {
    padding: theme.spacing(3)
  }
}));

export default function App() {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState(null);

  const handleClick = event => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);

  return (
    <div>
      <Button variant="contained" color="primary" onClick={handleClick}>
        Open Popover
      </Button>
      <Popover
        open={open}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "center"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "center"
        }}
      >
        <Typography className={classes.typography}>Popover content.</Typography>
      </Popover>
    </div>
  );
}

to add a button to open the popover and the popover itself.

The anchorEl prop has the anchor element of the popover, which is the button itself.

anchorOrigin specifies where relative to the button do we display the popover.

transformOrigin lets us change the position of the popover itself.

open sets whether the popover ios open or not.

If the anchorEl is set, then it’s open.

Otherwise, it’s not open.

onClose is a function that runs when the popover closes.

Mouse Over Interaction

We can open a popover when we move our mouse over an element.

For example, we can write:

import React from "react";
import Popover from "@material-ui/core/Popover";
import Typography from "@material-ui/core/Typography";
import { makeStyles } from "@material-ui/core/styles";

const useStyles = makeStyles(theme => ({
  popover: {
    pointerEvents: "none"
  },
  paper: {
    padding: theme.spacing(3)
  }
}));

export default function App() {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState(null);

  const handlePopoverOpen = event => {
    setAnchorEl(event.currentTarget);
  };

  const handlePopoverClose = () => {
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);

  return (
    <div>
      <Typography
        onMouseEnter={handlePopoverOpen}
        onMouseLeave={handlePopoverClose}
      >
        Hover me
      </Typography>
      <Popover
        className={classes.popover}
        classes={{
          paper: classes.paper
        }}
        open={open}
        anchorEl={anchorEl}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "left"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "left"
        }}
        onClose={handlePopoverClose}
        disableRestoreFocus
      >
        <Typography>some popover.</Typography>
      </Popover>
    </div>
  );
}

We pass in functions to the onMouseEnter prop to let us open the popover when we hover over the text.

Similarly, we pass in a function to the onMouseLeave prop to close the modal when our mouse leaves the element respectively.

The other parts are the same as the previous example.

PopupState Helper

To make managing the popover state easier, we can use the material-ui-popup-state library to manage the state.

To install it, we run:

npm install --save material-ui-popup-state

Then we can write:

import React from "react";
import Typography from "@material-ui/core/Typography";
import Box from "@material-ui/core/Box";
import Button from "@material-ui/core/Button";
import Popover from "@material-ui/core/Popover";
import PopupState, { bindTrigger, bindPopover } from "material-ui-popup-state";

export default function App() {
  return (
    <PopupState variant="popover">
      {popupState => (
        <div>
          <Button
            variant="contained"
            color="primary"
            {...bindTrigger(popupState)}
          >
            Open Popover
          </Button>
          <Popover
            {...bindPopover(popupState)}
            anchorOrigin={{
              vertical: "bottom",
              horizontal: "center"
            }}
            transformOrigin={{
              vertical: "top",
              horizontal: "center"
            }}
          >
            <Box p={3}>
              <Typography>some popover.</Typography>
            </Box>
          </Popover>
        </div>
      )}
    </PopupState>
  );
}

We have the PopupState coponent wirh the variant set to popover to display a popover.

Then inside it, we have a function that takes the popupState parameter, which has the open state of the popover.

We use the bindTrigger with it to return an object to toggle the popup in the button.

In the popover, we call bindPopover to bind the open prop to the popupState .

The rest of the code is the same as previous examples.

Conclusion

We can add popovers with the Popover component.

The material-ui-popup-state library can make managing the popover state easier.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *